#include <iostream>
#include <thread>
#include <mutex>
#include <List>
#include <future>
#include <vector>

using namespace std;

class ProcessMsg
{
public:
    void inMsg()
    {
        for (size_t i = 0; i < Num; i++)
        {
            msg_.push_back(i);
            cout << "The " << i << "th" << endl;
        }
    }

    int outMsg()
    {
        for (size_t i = 0; i < Num; i++)
        {
            int order= 0;
            if (!msg_.empty())
            {
                order = msg_.front();
                msg_.pop_front();
            }
            cout << "order is : " << order << endl;
        }
        return 0;

    }

    int getSum(int num)
    {
        int result = 0;
        for (size_t i = 0; i < num; i++)
        {
            result += i;
        }
        return result;

    }

    void operator()() {
        cout << "This is a callable class!" << endl;
    }

private:
    std::list<int> msg_;
    int Num = 100000;
};


template <class T>
void calTime(T&& func)
{
    using namespace std::chrono;
    auto start = system_clock::now();

    func();

    duration<double> elapsed = system_clock::now() - start;
    cout << "diff = " << elapsed.count() << endl;

}

double getSum1(int start, int end)
{
    double result = 0;
    for (size_t i = start; i < end; i++)
    {
        result += i;
    }
    return result;

}

const long S = 100000000;
const int K = 4;
int main()
{
    using namespace std::chrono;

    ProcessMsg promsg;

    // std::thread th1(&ProcessMsg::inMsg,  &promsg);
    // std::thread th2(&ProcessMsg::outMsg, &promsg);
    // th1.join();
    // th2.join();

    // calTime([](){
    //     std::future<double> fut1 = std::async(getSum1, 0, 500000000);
    //     std::future<double> fut2 = std::async(getSum1, 500000000, 1000000000);// 任务分解
    //     auto diff1 = fut1.get();
    //     auto diff2 = fut2.get();
    //     cout << diff1 + diff2 << endl;
    // });

    // calTime([](){
    //     std::future<double> fut3 = std::async(getSum1, 0, 1000000000);
    //     auto diff3 = fut3.get();
    //     cout << diff3 << endl;

    // });


    calTime([](){
        std::vector<std::future<double>> v_fut;
        for (size_t i = 0; i < K; i++)
        {
            v_fut.push_back(std::async(getSum1, i==0 ? 0 : (S/K)*i, (S/K)*(i+1)));
        }
        double res = 0.0;
        for (size_t i = 0; i < K; i++)
        {
            res += v_fut[i].get();
        }
        cout << "result1 = " << res << endl;
    
    });

    calTime([](){
        std::future<double> fut3 = std::async(getSum1, 0, S);
        auto res = fut3.get();
        cout << "result2 = " << res << endl;


    });

    return 0;
}

// above code is not inluce mutex lock, but in this envorienment is ok!
// The above code should be added mutex lock.